package no.uib.hplims.views.settings;

import java.util.List;

import no.uib.hplims.models.User;
import no.uib.hplims.tools.SecurityUtil;

import org.vaadin.appfoundation.authentication.SessionHandler;
import org.vaadin.appfoundation.authentication.exceptions.InvalidCredentialsException;
import org.vaadin.appfoundation.authentication.exceptions.PasswordsDoNotMatchException;
import org.vaadin.appfoundation.authentication.util.PasswordUtil;
import org.vaadin.appfoundation.authentication.util.UserUtil;
import org.vaadin.appfoundation.view.AbstractView;

import com.vaadin.data.Validator;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Window.Notification;
import com.vaadin.ui.themes.Runo;

public class RegularUserView extends AbstractView<VerticalLayout> implements
		Button.ClickListener {

	private static final long serialVersionUID = -8061491980341820223L;

	private VerticalLayout mainContent = null;
	private VerticalLayout editorArea = null;

	private TextField nameField = null;
	private TextField emailField = null;
	private TextField usernameField = null;
	private PasswordField currentPasswordField = null;
	private PasswordField passwordField = null;
	private PasswordField repeatPasswordField = null;

	private User selectedUser = null;

	private Button submitButton = null;
	private Button cancelButton = null;

	public RegularUserView() {
		super(new VerticalLayout());

		mainContent = getContent();
		mainContent.setMargin(true, true, true, true);
		mainContent.setSpacing(true);

		Label header = new Label("Edit your user details");
		header.setStyleName(Runo.LABEL_H2);
		mainContent.addComponent(header);

		initEditorArea((User) SessionHandler.get());
	}

	public void activated(Object... params) {
		System.out.println("Activated AdminUserView");
	}

	public void deactivated(Object... params) {

	}

	private void initEditorArea(User user) {
		selectedUser = user;
		if (editorArea == null) {
			editorArea = new VerticalLayout();
			editorArea.setVisible(false);

			usernameField = new TextField("Username");
			usernameField.setEnabled(false);
			nameField = new TextField("Name");
			emailField = new TextField("Email");
			currentPasswordField = new PasswordField("Current password");
			passwordField = new PasswordField("Password");
			passwordField.setImmediate(true);
			repeatPasswordField = new PasswordField("Repeat password");
			repeatPasswordField.setImmediate(true);
			
			List<Validator> validators = PasswordUtil.getValidators();
			for (Validator val : validators) {
				passwordField.addValidator(val);
				repeatPasswordField.addValidator(val);
			}

			submitButton = new Button("Update");
			submitButton.addListener(this);
			cancelButton = new Button("Cancel");
			cancelButton.addListener(this);

			editorArea.addComponent(usernameField);
			editorArea.addComponent(nameField);
			editorArea.addComponent(emailField);
			editorArea.addComponent(currentPasswordField);
			editorArea.addComponent(passwordField);
			editorArea.addComponent(repeatPasswordField);

			HorizontalLayout footer = new HorizontalLayout();
			footer.addComponent(submitButton);
			footer.addComponent(cancelButton);
			editorArea.addComponent(footer);

			mainContent.addComponent(editorArea);
		}
		resetFields();

		if (selectedUser != null) {
			nameField.setValue(selectedUser.getName());
			emailField.setValue(selectedUser.getEmail());
			usernameField.setValue(selectedUser.getUsername());

			currentPasswordField.setVisible(true);
			nameField.setRequired(false);
			emailField.setRequired(false);
			usernameField.setRequired(false);
			passwordField.setRequired(false);
			repeatPasswordField.setRequired(false);
		}
		editorArea.setVisible(true);
	}

	private boolean editExistingUser() {

		if (selectedUser != null) {
			String name = (String) nameField.getValue();
			String email = (String) emailField.getValue();
			String username = (String) usernameField.getValue();
			String currentPassword = (String) currentPasswordField.getValue();
			String password = (String) passwordField.getValue();
			String repeatPassword = (String) repeatPasswordField.getValue();
			try {
				if (!password.isEmpty() || !repeatPassword.isEmpty()) {
					if (SecurityUtil.passwordIsValid(password)) {
						SecurityUtil.changePassword(selectedUser,
								currentPassword, password, repeatPassword);
					}
				}
				
				if (emailField.getValue() != null
						&& emailField.getValue() != "") {
					selectedUser.setEmail((String) emailField.getValue());
				}
				if (nameField.getValue() != null && nameField.getValue() != "") {
					selectedUser.setName((String) nameField.getValue());
				}

				UserUtil.storeUser(selectedUser);
			} catch (InvalidCredentialsException e) {
				invalidCredentialsException();
				return false;
			} catch (PasswordsDoNotMatchException e) {
				passwordsDoNotMatchException();
				return false;
			}
			getWindow().showNotification("Successful!",
					"Your user information has been updated.",
					Notification.TYPE_TRAY_NOTIFICATION);
			return true;
		}
		return false;	
	}

	private void invalidCredentialsException() {
		currentPasswordField
				.setComponentError(new Validator.InvalidValueException(
						"Invalid password"));
	}
	
	private void passwordsDoNotMatchException() {
		this.passwordField
				.setComponentError(new Validator.InvalidValueException(
						"Passwords did not match"));
		this.repeatPasswordField
				.setComponentError(new Validator.InvalidValueException(
						"Passwords did not match"));
	}

	private void removeErrors() {
		this.nameField.setComponentError(null);
		this.emailField.setComponentError(null);
		this.usernameField.setComponentError(null);
		this.currentPasswordField.setComponentError(null);
		this.passwordField.setComponentError(null);
		this.repeatPasswordField.setComponentError(null);
	}

	private void resetFields() {
		this.nameField.setValue(selectedUser.getName());
		this.emailField.setValue(selectedUser.getEmail());
		this.usernameField.setValue(selectedUser.getUsername());
		this.currentPasswordField.setValue("");
		this.passwordField.setValue("");
		this.repeatPasswordField.setValue("");
	}

	public void buttonClick(ClickEvent event) {
		if (event.getButton() == submitButton) {
			removeErrors();
			editExistingUser();
			// TODO: Give feedback if (un)successful
			resetFields();
		} else {
			resetFields();
			removeErrors();
		}
	}

}
